﻿using System;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace Toenda.Foundation.SystemLayer {
	internal static class NativeMethods {
		[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
		[return: MarshalAs(UnmanagedType.Bool)]
		internal static extern bool VerifyVersionInfo(
			ref NativeStructs.OSVERSIONINFOEX lpVersionInfo,
			uint dwTypeMask,
			ulong dwlConditionMask);

		[DllImport("kernel32.dll")]
		internal static extern ulong VerSetConditionMask(
			ulong dwlConditionMask,
			uint dwTypeBitMask,
			byte dwConditionMask);

		[DllImport("kernel32.dll", SetLastError = true)]
		[return: MarshalAs(UnmanagedType.Bool)]
		internal static extern bool DeviceIoControl(
			IntPtr hDevice,
			uint dwIoControlCode,
			IntPtr lpInBuffer,
			uint nInBufferSize,
			IntPtr lpOutBuffer,
			uint nOutBufferSize,
			ref uint lpBytesReturned,
			IntPtr lpOverlapped);

		[DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
		[return: MarshalAs(UnmanagedType.Bool)]
		internal static extern bool ShellExecuteExW(ref NativeStructs.SHELLEXECUTEINFO lpExecInfo);

		[DllImport("kernel32.dll", SetLastError = true)]
		[return: MarshalAs(UnmanagedType.Bool)]
		internal static extern bool GlobalMemoryStatusEx(ref NativeStructs.MEMORYSTATUSEX lpBuffer);

		[DllImport("shell32.dll", SetLastError = false)]
		internal static extern void SHAddToRecentDocs(uint uFlags, IntPtr pv);

		[DllImport("kernel32.dll", SetLastError = false)]
		internal static extern void GetSystemInfo(ref NativeStructs.SYSTEM_INFO lpSystemInfo);

		[DllImport("kernel32.dll", SetLastError = false)]
		internal static extern void GetNativeSystemInfo(ref NativeStructs.SYSTEM_INFO lpSystemInfo);

		[DllImport("Wintrust.dll", PreserveSig = true, SetLastError = false)]
		internal extern static unsafe int WinVerifyTrust(
			IntPtr hWnd,
			ref Guid pgActionID,
			ref NativeStructs.WINTRUST_DATA pWinTrustData
			);

		[DllImport("SetupApi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
		internal static extern IntPtr SetupDiGetClassDevsW(
			ref Guid ClassGuid,
			[MarshalAs(UnmanagedType.LPWStr)] string Enumerator,
			IntPtr hwndParent,
			uint Flags);

		[DllImport("SetupApi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
		[return: MarshalAs(UnmanagedType.Bool)]
		internal static extern bool SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);

		[DllImport("SetupApi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
		[return: MarshalAs(UnmanagedType.Bool)]
		internal static extern bool SetupDiEnumDeviceInfo(
			IntPtr DeviceInfoSet,
			uint MemberIndex,
			ref NativeStructs.SP_DEVINFO_DATA DeviceInfoData);

		[DllImport("SetupApi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
		[return: MarshalAs(UnmanagedType.Bool)]
		internal static extern bool SetupDiGetDeviceInstanceIdW(
			IntPtr DeviceInfoSet,
			ref NativeStructs.SP_DEVINFO_DATA DeviceInfoData,
			IntPtr DeviceInstanceId,
			uint DeviceInstanceIdSize,
			out uint RequiredSize);

		internal static void ThrowOnWin32Error(string message) {
			int lastWin32Error = Marshal.GetLastWin32Error();

			if(lastWin32Error != NativeConstants.ERROR_SUCCESS) {
				throw new Win32Exception(lastWin32Error, message + " (" + lastWin32Error.ToString() + ")");
			}
		}
	}
}
